﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class World : MonoBehaviour
{
	/// <summary>
	/// 맵 로딩 모드
	/// </summary>
	public enum MapLoadingMode
	{
		Static,				// 맵에 이미 chunk가 배치되어있음
		Dynamic,			// chunk를 따로 로드해야함
	}


	// Constants

	public const float		c_mapChunkWidth	= 96;					// 맵 조각당 가로 사이즈



	// Properties

	[SerializeField]
	MapLoadingMode	m_loadingMode;
	[SerializeField]
	GameObject		m_eventReceiver;							// 이벤트 리시버 (자동으로 세팅될 수도 있음)



	// Members

	List<GameObject>	m_mapChunks	= new List<GameObject>();	// 맵 조각 리스트



	/// <summary>
	/// 카메라 X축 이동 범위 (최소)
	/// </summary>
	/// <value>The camera X position minimum.</value>
	public float cameraXPosMin
	{
		get
		{
			return 0;
		}
	}

	/// <summary>
	/// 카메라 X축 이동 범위 (최대)
	/// </summary>
	/// <value>The camera X position max.</value>
	public float cameraXPosMax
	{
		get 
		{
			return c_mapChunkWidth * (m_mapChunks.Count - 1);
		}
	}


	void Awake()
	{
		if(m_loadingMode == MapLoadingMode.Static)			// * 이미 씬에 맵 조각들을 배치해놓은 경우, 스캔
		{
			ScanMapChunks();
		}
	}


	/// <summary>
	/// 이미 배치된 맵 조각들을 모은다
	/// </summary>
	void ScanMapChunks()
	{
		m_mapChunks.Clear();

		GameObject[] chunks	= GameObject.FindGameObjectsWithTag("MapChunk");
		m_mapChunks.AddRange(chunks);
	}



	public Vector3 WorldToLocalPosition(Vector3 worldPos)
	{
		return transform.worldToLocalMatrix * worldPos;
	}

	public Vector3 LocalToWorldPosition(Vector3 localPos)
	{
		return transform.localToWorldMatrix * localPos;
	}

	/// <summary>
	/// 월드 이벤트 보내기
	/// </summary>
	/// <param name="eventName">Event name.</param>
	public void SendWorldEvent(string eventName, object parameter = null)
	{
		if(m_eventReceiver != null)
		{
			m_eventReceiver.SendMessage(eventName, parameter);
		}
	}



	/// <summary>
	/// 월드 로딩
	/// </summary>
	/// <param name="worldInfo">World info.</param>
	public void LoadWorld(WorldInfo worldInfo)
	{
		if(m_loadingMode != MapLoadingMode.Dynamic)
		{
			Debug.LogWarning("Dynamic loading is not allowed when MapLoadingMode is not set to Dynamic.");
		}
		else
		{
			Transform worldT		= transform;

			foreach(string path in worldInfo.mapChunkPaths)				// 맵 먼저 로딩
			{
				int oldChunkCount	= m_mapChunks.Count;

				string fullPath		= Constants.Path.mapChunk + path;
				GameObject prefab	= ResourceDepot.Load<GameObject>(fullPath);		// 맵 조각 인스턴스 생성
				GameObject chunkGO	= Instantiate(prefab) as GameObject;

				Transform chunkT	= chunkGO.transform;							// 위치 맞춰주기
				chunkT.parent		= worldT;
				float chunkXPos		= ((float)oldChunkCount) * c_mapChunkWidth;
				chunkT.localPosition	= Vector3.right * chunkXPos;

				m_mapChunks.Add(chunkGO);
			}

			int clearCount			= CodexManager.clearCount;

			foreach(WorldInfo.CharInfo charInfo in worldInfo.charInfos)		// 캐릭터 생성
			{
				if (charInfo.appearanceClearCount > clearCount)				// 아직 등장할 때가 아니라면 스킵...
					continue;

				string fullPath		= Constants.Path.character + charInfo.prefabPath;	// 프리팹 생성
				GameObject prefab	= ResourceDepot.Load<GameObject>(fullPath);
				GameObject charGO	= Instantiate(prefab) as GameObject;

				Transform charT		= charGO.transform;									// 위치 맞춰주기
				charT.parent		= worldT;
				charT.localPosition	= new Vector3(charInfo.position.x - c_mapChunkWidth / 2f, charInfo.position.y, 0);
			}

			if(!string.IsNullOrEmpty(worldInfo.worldEventReceiverPath))					// 이벤트 리시버가 지정된 경우 생성해주기
			{
				string fullPath		= Constants.Path.worldEventReceiver + worldInfo.worldEventReceiverPath;
				GameObject prefab	= ResourceDepot.Load<GameObject>(fullPath);
				m_eventReceiver		= Instantiate(prefab) as GameObject;
			}
		}
	}
}
